%option c++
%option yylineno
%option noyywrap
%option caseless

%{
#include "token.h"
OpType Oper=op_NONE;
DataType Type=dt_NONE;
%}

newline 	[\n]
space       [ ]
tab 		[\t] 
letter 		[A-Za-z] 
digit 		[0-9]
id 			{letter}({letter}|{digit}){0,254}
illegalid	{letter}({letter}|{digit})*

digits	{digit}{digit}*
int_num	{digits}
optional_fraction	(\.{int_num})?
optional_exponent	(E[+\-]?{int_num})?
real_num			{int_num}{optional_fraction}{optional_exponent}

comment \{.*\}

%%

{space} 	{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_SPACE);}
{tab}		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_TAB);}
{newline}	{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_NEWLINE);}
{comment} 	{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_COMMENT);}
Program		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_PROGRAM);}
Var			{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_VAR);}
If 			{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_IF);}
then 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_THEN);}
else 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_ELSE);}
".."		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_DOTDOT);}

array		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_ARRAY);}
of			{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_OF);}
integer     { Oper = op_NONE; Type = dt_KEYWORD; return(tc_INTEGER);}
real        { Oper = op_NONE; Type = dt_KEYWORD; return(tc_REAL);}
{int_num}	{ Oper = op_NONE; Type = dt_INTEGER; return(tc_NUMBER);}
{real_num}	{ Oper = op_NONE; Type = dt_REAL; return(tc_NUMBER);}
function	{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_FUNCTION);}
procedure	{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_PROCEDURE);}
begin		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_BEGIN);}
end			{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_END);}
while		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_WHILE);}
do			{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_DO);}
not			{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_NOT);}
or		 	{ Oper = op_OR; Type = dt_OP; return(tc_ADDOP);} 
div 		{ Oper = op_DIV; Type = dt_OP; return(tc_MULOP);}
mod 		{ Oper = op_MOD; Type = dt_OP; return(tc_MULOP);} 
and 		{ Oper = op_AND; Type = dt_OP; return(tc_MULOP);}
{id}   		{ Oper = op_NONE; Type = dt_ID; return(tc_ID);}
{illegalid} { Oper = op_NONE; Type = dt_ID; return(tc_ERROR2);}

"<" 		{ Oper = op_LT; Type = dt_OP; return(tc_RELOP);} 
"<=" 		{ Oper = op_LE; Type = dt_OP; return(tc_RELOP);} 
"=" 		{ Oper = op_EQ; Type = dt_OP; return(tc_RELOP);} 
"<>" 		{ Oper = op_NE; Type = dt_OP; return(tc_RELOP);} 
">" 		{ Oper = op_GT; Type = dt_OP; return(tc_RELOP);} 
">=" 		{ Oper = op_GE; Type = dt_OP; return(tc_RELOP);}
":="		{ Oper = op_NONE; Type = dt_OP; return(tc_ASSIGNOP);}
"(" 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_LPAREN);} 
")" 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_RPAREN);} 
"[" 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_LSQBRACKET);} 
"]" 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_RSQBRACKET);}
"{" 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_LBRACKET);} 
"}" 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_RBRACKET);} 
":" 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_COLON);} 
";" 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_SEMICOL);} 
"," 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_COMMA);} 
"." 		{ Oper = op_NONE; Type = dt_KEYWORD; return(tc_DOT);} 
"-" 		{ Oper = op_MINUS; Type = dt_OP; return(tc_ADDOP);} 
"+" 		{ Oper = op_PLUS; Type = dt_OP; return(tc_ADDOP);} 
"*" 		{ Oper = op_MULT; Type = dt_OP; return(tc_MULOP);} 
"/" 		{ Oper = op_DIVIDE; Type = dt_OP; return(tc_MULOP);}
.			{ Oper = op_NONE; Type = dt_NONE; return(tc_ERROR);}


%%